package net.myspring.middle.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.myspring.common.handsontable.HandSonTableUtils;
import net.myspring.common.mybatis.domain.Page;
import net.myspring.common.mybatis.domain.Pageable;
import net.myspring.common.utils.Collections3;
import net.myspring.common.utils.Const;
import net.myspring.common.utils.ObjectMapperUtils;
import net.myspring.common.utils.StringUtils;
import net.myspring.common.ztree.TreeNode;
import net.myspring.middle.domain.Menu;
import net.myspring.middle.domain.Permission;
import net.myspring.middle.mapper.MenuMapper;
import net.myspring.middle.mapper.PermissionMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.HtmlUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by liuj on 16/7/10.
 */
@Service
public class PermissionService {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private MenuMapper menuMapper;

    public Page<Permission> findPage(Pageable pageable, Map<String, Object> map) {
        Page<Permission> page = permissionMapper.findPage(pageable, map);
        return page;
    }

    public Permission findOne(String id) {
        return permissionMapper.findOne(id);
    }


    public List<Permission> findByRoleId(String roleId) {
        return permissionMapper.findByRoleId(roleId);
    }

    @Transactional
    public Permission save(Permission permission, List<String> idList) {
        boolean isCreate = permission.isCreate();
        if (isCreate) {
            permissionMapper.save(permission);
        } else {
            permissionMapper.update(permission);
        }
        idList.add(permission.getId());
        return permission;
    }

    public List<List<Object>> findAllData() {
        List<List<Object>> dataList = Lists.newArrayList();
        List<Permission> permissions = permissionMapper.findAll();
        for (Permission permission : permissions) {
            permission.setMenu(menuMapper.findOne(permission.getMenuId()));
            List<Object> row = Lists.newArrayList();
            row.add(permission.getId().toString());
            row.add(permission.getMenu().getName());
            row.add(permission.getName());
            row.add(permission.getCode());
            dataList.add(row);
        }
        return dataList;
    }

    @Transactional
    public void save(String data) {
        data = HtmlUtils.htmlUnescape(data);
        List<List<Object>> datas = ObjectMapperUtils.readValue(data, ArrayList.class);
        if (Collections3.isEmpty(datas)) {
            return;
        }
        List<String> idList = Lists.newArrayList();
        for (List<Object> row : datas) {
            String id = HandSonTableUtils.getValue(row, 0);
            String menuName = HandSonTableUtils.getValue(row, 1);
            String name = HandSonTableUtils.getValue(row, 2);
            String code = HandSonTableUtils.getValue(row, 3);
            if (StringUtils.isEmpty(menuName) && StringUtils.isEmpty(name) && StringUtils.isEmpty(code)) {
                continue;
            }
            Permission permission;
            if (StringUtils.isEmpty(id)) {
                permission = new Permission();
            } else {
                permission = permissionMapper.findOne(id);
            }
            permission.setMenu(menuMapper.findByName(menuName));
            permission.setName(name);
            permission.setCode(code);
            save(permission, idList);
        }
        if (Collections3.isNotEmpty(idList)) {
            permissionMapper.deleteByIdNotIn(idList);
        } else {
            permissionMapper.deleteAll();
        }
    }

    public String check(String data) {
        StringBuilder stringBuilder = new StringBuilder();
        List<List<Object>> datas = ObjectMapperUtils.readValue(data, ArrayList.class);
        //检查编码是否重复
        Map<String, Integer> codeMap = Maps.newHashMap();
        for (List<Object> row : datas) {
            String code = HandSonTableUtils.getValue(row, 3);
            if (!codeMap.containsKey(code)) {
                codeMap.put(code, 0);
            }
            codeMap.put(code, codeMap.get(code) + 1);
        }
        codeMap.keySet().stream().filter(key -> codeMap.get(key) > 1).forEach(key -> {
            stringBuilder.append("编码：" + key + " 有" + codeMap.get(key) + "个").append(Const.CharEnum.BR.getValue());
        });
        return stringBuilder.toString();
    }


    public List<TreeNode> findPermissionTree(List<Menu> menus, List<String> permissionIds) {
        //拥有的权限
        Set<String> permissionIdSet = Sets.newHashSet();
        if (Collections3.isNotEmpty(permissionIds)) {
            permissionIdSet.addAll(permissionIds.stream().map(String::valueOf).collect(Collectors.toList()));
        }
        //所有权限
        Map<String, List<Permission>> permissionMap = getPermissionMap();
        List<TreeNode> list = Lists.newArrayList();
        sortList(list, menus, permissionIdSet, permissionMap);
        return list;
    }

    private List<TreeNode> sortList(List<TreeNode> list, List<Menu> menus, Set<String> permissionIdSet, Map<String, List<Permission>> permissionMap) {
        for (Menu menu : menus) {
            if (!Menu.MenuType.FUNCTION.getName().equals(menu.getTypeLabel())) {
                TreeNode treeNode = new TreeNode("menu_" + menu.getId(), "menu_" + menu.getParentId(), menu.getName(), false, true, true);
                list.add(treeNode);
                if (Menu.MenuType.NAVIGATION_GROUP.getName().equals(menu.getTypeLabel())) {
                    if (Collections3.isNotEmpty(menu.getChildList())) {
                        sortList(list, menu.getChildList(), permissionIdSet, permissionMap);
                    }
                } else if (Menu.MenuType.NAVIGATION.getName().equals(menu.getTypeLabel())) {
                    if (Collections3.isNotEmpty(permissionMap.get(menu.getId()))) {
                        for (Permission permission : permissionMap.get(menu.getId())) {
                            String id = String.valueOf(permission.getId());
                            boolean checked = permissionIdSet.contains(id);
                            treeNode = new TreeNode(id, "menu_" + menu.getId(), permission.getName(), checked, false, true);
                            list.add(treeNode);
                        }
                    }
                }
            }
        }
        return list;
    }

    private Map<String, List<Permission>> getPermissionMap() {
        Map<String, List<Permission>> permissionMap = Maps.newHashMap();
        List<Permission> permissions = permissionMapper.findAll();
        for (Permission permission : permissions) {
            if (!permissionMap.containsKey(permission.getMenuId())) {
                permissionMap.put(permission.getMenuId(), new ArrayList<Permission>());
            }
            permissionMap.get(permission.getMenuId()).add(permission);
        }
        return permissionMap;
    }
}
